package cn.maihe.elg.operation.utils;

import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.util.encoders.Base64;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

public class SM2Util {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static void main(String[] args) throws Exception {
//        // 1. 加载证书和私钥
//        String cerPath = "sm2.crt"; // CER证书文件路径
//        String p12Path = "sm2.p12"; // PKCS12文件路径
//        String p12Password = "123456"; // PKCS12密码
        // 1. 加载证书和私钥
        String cerBase64 = "MIIEpDCCA4ygAwIBAgIPBwADICIRAREAAANpMyV4MA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNVBAYTAkNOMQ8wDQYDVQQIDAbph43luoYxDzANBgNVBAcMBumHjeW6hjESMBAGA1UECgwJaWZ1dHVyZWNhMRIwEAYDVQQLDAnov5Dnu7Tpg6gxFDASBgNVBAMMC1JTQTIwNDhURVNUMB4XDTIyMTEwMTAyNDcyN1oXDTI3MTAzMTAyNDcyN1owgaQxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAnnpo/lu7rnnIExEjAQBgNVBAcMCeWOpumXqOW4gjEYMBYGA1UECgwP5L+d6K+B5Lq65py65p6EMRgwFgYDVQQLDA/kv53or4HkurrmnLrmnoQxEjAQBgNVBAsMCXVzY2k6Y3NzYzElMCMGA1UEAwwc5rWL6K+VLeS/neivgeS6uuacuuaehOivgeS5pjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOVxyUNClGgAkFX+A2ke9En50Ch426IzNRbu02QKjWYtNUtoHUiqE1tgQ+bcVgaUjrzsMyOD65O2/Ih5gp3Jjcyg8UsNF5NFjL83LPjYkyssfXsWzjPLGbXv0fAo7lehttboHF+ZUPaq5dW/IxKVctFDuph5kjx021Es9YRGHGazqQPEtydnhCrv1DgHun0lrjMCxLxm17gxXkpx9ZprwKN4fWEmwYXv4fLFEieKhItKanSxowf0tyxYowSo1w660Xp/wx/qxji8qkLZ8hsqCCzYYaGN205LCIGS248oCVU4Draz1iSV86Xkr10ImihAtEfAubV/I9AablIFeziK6kCAwEAAaOCAQcwggEDMB8GA1UdIwQYMBaAFOViSyOeheTxjv3Zi2p9fkIPLxuXMB0GA1UdDgQWBBQfkfHGWaV13MidBsGBKKpupSUKKzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIGwDAwBgkqgRyHhDMGAQEBAf8EIGZmNjVkNmM0NDA2ZjExZWNhNzA3MDAwYzI5MTg4ZTFmMEoGA1UdYwRDWFkyZDVhYzczOWViZWJjM2QwMGViMWJjN2Y4M2YxOTQyNzcwZTc2ZmQ3Y2QwMzI3MjYzOWQwODY3MDk2MmNkY2RmMjAiBgkqgRyHhDMEAQMBAf8EEjkxNTAwMDAwMzIyMzkyMjkyWDANBgkqhkiG9w0BAQsFAAOCAQEAk1gVtzrV6CX3D7mPVjwE111FN+5BZMp2L+SNW707mVrw1s5+xar2r4QnSgsrDkdXMDuaNjbj6L3BcAEYUKHLN+8xe4tIMYxuneLfqJiyyy6lYSwqeuvuIH9yhjFaK5bt4Ix3YQ6QMgv/LI0932uLWAnoSDhNyHOBzQkEgSU7yIFUKGPdFHums/tJVvD6KPR6QgFZC6ENmg+lUvmX6uu19ScaRtR/nuzgkbCsZaMAMk28PpSwJlHqY2Y8vNSXuGiiY9gky3dpoF6qJ4dx/SdugG+lDVq4zGEZoU1JjSCY2hPNUqhVo10Rh/51UwE5UY//u4aSthjBmInGOuIknrpx+w=="; // CER证书文件路径
        String p12Base64 = "MIILtQIBAzCCC24GCSqGSIb3DQEHAaCCC18EggtbMIILVzCCBaMGCSqGSIb3DQEHAaCCBZQEggWQMIIFjDCCBYgGCyqGSIb3DQEMCgECoIIE+zCCBPcwKQYKKoZIhvcNAQwBAzAbBBR4bT90cSAgXePVrGVmDZQCm3U9fQIDAMNQBIIEyEsEFQgosG/Mc0xAeVeThxsJqGCesvpTfLz7NPMCz8fCedOIdfU23y85ls/jO/i9adQcpW9hnMJK+w6pGhGVkRr3aB/CPkelk1/+3Fb6YlkWkQPs3TMvOyAzv0CHCB4ApfeUny8IT6W1Vwhv2VrIuBEhQsXhylvLV3Uh86YdMohnnQrdbqBua0b4imSbt7+KsuiUH2nA/BEUb9vbnpFKvElFPmfYnP+Z4iP3+vRxJV25ymwZelx+eXgB8YG1Dd5WGVN6ulqe+LiGYTA4/DiQJbCElIlFvfOdu+MD8MW03LhMOHtMoZMch8kfpTrNIYICREOYDxY7UbaDDGT+Ad18s9geA5KxD/S+4w+NSKbGoaPM8BaZS2JpU/yEFZQo2eCRrxPZv76nfQ9QCWq7sEDbf4Gz67KfBp+qQYzSWQpmiEo1j96O4B8/KhhVATNwdlSkWxR61KLv6ZiKzA0Be8a84p2j5o+NV6B0KuwH/YXdHKAiwkojm/r72Jz8piPGeNdKEmTVTLqsDIj4xJUPiNA8fdnTUypw6lMVQ6yarVQR//xSQpzAVlqPKL2plm6PAwqI3ByTGxizsdwJWfuWkF8j4KH2wsjQDa584bpr+ndEmho193U6ugAXc+bEUGYsT+F+zu2OQqvQRVcHwQkvzfVreRe/RBxFREEhfPhrRQZedpXMaFjN3L5pNS7AsY69WEuZDkCFzmSIfCxhxZ7vfwgzpNZiT9RLFq1dn0ZZIxGmCmI/XiQKJSxkU4vwTw8LyZQIFjacjtN42WW8z/xy0/1RNtYfOtTHJOCq0BZA/NCUdyWRAW3NIGbi/GwixoZ5W7CkPu8qbenaykUDye8UpYFTwLw0CDrOanF0iOR2Rf4VYTBu27zDIAPcq4INtvZpxxxKp+M5FVXU14541+/C/vSquTLwmN9tIIeoFYpGbwTG1ZvXXpa0ojLX3fYHGkw/GQOAvFp2AQrKmmot/Bz8uZTxUhJYRETevGVkh8B8Px13Z+nvMsj0XkJTV1fclwSDKXcPWSXaQ6Hp7NcNROq2K1LB3/PCeDULJd9pfV3XcMZByaHusY5hvZOeKpASEKiA2v4LZO97/xOmZxZU3HTnlBGijZmqjK3RAUYA6UObrmyFvSzTkMCzXZKFMgpjcQvJwHr3hv/PsRmD5Is/a1clTdLXATD/RLnLtfdXOVe95oQlaBmYQGrju8/w5AejZWovvu7uPViUsid+zjbGXjpZSp0ZmbIRpnjdq+8C6Fbs3n0gWOxCsWkA7qGa5/z6PNKK+zs7tDMuOgSFH7Wn95Zin43z5KQ4FIKFL6IUKD0iKa8QHWwaZOnVGOvQCkl4H1fRZp9aj5NCKE3/xe6HrKWDEFkh27idIGVTcrzgp4MnrKRFfL30s848ABlGOiUMMLB48pRJGA+hz29bbbFpJn0cRVg6++z4DTXZX2Kwra9kouAUSAfJVf9j31syCaty+x2R47kR1LGqTAqOXFTSothxbxQ92hVjfu//Bt+a7lX71Zg+H//h4k47GIMqARxR3bpaXxO37M9frW5YVrh4x7PONMWwif3iLP/wavkvJDxdd5NB2Z4zrTk0yO4tTruc9YcT4zZ99ojjPHgYnwtrG9suTBTtZ7MmlvBy/4wKgTF6MFUGCSqGSIb3DQEJFDFIHkYAMwA2ADMANAA2ADMAMgA1ADYAMwA4ADkAMwA1ADQAMgA4ADIANAA0ADUAOQA3ADgAMQA3ADAANAAyADIAMQA2ADMAMQAyMCEGCSqGSIb3DQEJFTEUBBJUaW1lIDE2NjcyNzA4ODA1OTIwggWsBgkqhkiG9w0BBwagggWdMIIFmQIBADCCBZIGCSqGSIb3DQEHATApBgoqhkiG9w0BDAEGMBsEFCxIcE5+TufnB6EScXrvezbnzoYkAgMAw1CAggVYPOUIUveJTWJuqtPyqicwdYUtkf1+BawAUkadetMlODPtk93dYMAwji9FuN8+s3q3DYcj7cIOxeIRNBnjLQ0tdZA1P3LDNkr0VJ4ZWIJYXOmgo+eW03GhygfNpi4n9EitgIgvo3hBgCkb7VpF3pH4ojaj32+AZ7LfdlvgcDAWfudOkQfaogCIPmZsX+IMCVvxegOECvkUXmUp6f0sTMTvvva3fZt/5Rg5om3pBqlPh+yjF0JBLPKaWqWWQbQ1qQW7DxLksvKcbSCBLKO4j/jUWIOtaYQ7C+6/NP1hoq+OELZwPMBkmw1xnUxUW5wcn7pRENLTu8hAw8oClutIwaplvA0zoHyS03Qx8BcfTveS4b8qTGPl3d0igw7XXPw6W7J6sRe15s5Bj0lJUadTc2vdVrc1uhBNimM5gNBkE28rqDHYkXi1bgCSDrnE+JBabTNcSQ09ogY0sagbME7LBXhdXr5rngdADlufq4S2TdIV2eOdFkBOGsrolDHURW7lrsAVVpP88+oTxL3Lqk26GBWGm0IB9+badupqYxk64/WSb0vLiETq9nZXKw8fnGiOHzj/sdcfw+CwidomM2sSizzojQwj5XphIHTmNp623/iz9tTzKPkM91hGFxH41vvlYgpOE/F9jKmywX8zEK+KrzdqnF5nR/ff+38kOEfOgXJkMsgXoW4uWEMqdUmNWUkO+ujLVcYhQDPL053RFCZU2/jfnStULDEs07a61CxC/KgsKtOzMPKD4Qs4HuOiceS14bPvwJm6ZkxV4R8MdfilPZZEufwPYqeb07v7Wata7vLvU4I+KFxxp/5gTCfKO46e1OTJPAi+wQxdXyj2iSqCfnIxcJv3S+m6Eb/haSwU/x0zZdf1fV5ZFfTaPgYTBlLV4t9WYDnD3m0fw3g1xxcLxhFvwjCTY+50cWPUuylTVSaGr5/7VmjHtMFFRgNtliQvp7NI96KN3SRdxJzJjQ65/3K2bw9SQMytwAYdU/uuWOH55ElTJZTTrqMqlBL3ZL6RXfJeo5gjokhol2igSEa1RyzEUEGE79S1Tzw00Qv1Jue8wcaZEDH5b86IUbdqAVBKg115XhBCj0S7rjED5UK1f1vJrcOvRTviKktAGjfcbKVak4YayeD0szzMylIXXmm0Sw3SzTbqacALhR8EpSqfvCLgaDiV67fkPjKcswwe5rWgLmzoWdFloKdVVBix4WeLAqb2vgPRleUhRhOjmRaZNaLDzj1y/8Ha01KmlW/dcf6/ys3QfHpicmKRlu6CPfF08JJ7so/vs4fTSvgdP8IRkXPAEfMY5MJWtYaJkYwnVxe2pW7+NLoOU9eij0jEerUiLNujuS0lRIK68pIs2SKslNq7ZJhxE+bqxjsxDTMOmT7YiebMG/kDO82yFlJW2k+0clsggfoh3sjBQzu3WBAn9F2hQ5/AvjWj9KiuDKNIBkZj+SVLQE2Hpz+4I2gcxWqtMZPvvAMJ6GFr9kJSbL0XqIxV11sOYAMkyj2Qcy86qMYK/EL6KktF4MM7oWQ1yeVbRpre0OpyLUH93JdosDxKC2vam52OhZbvT7t4lWwlGUiJmSFWVg+x/e6QhW0ThSvJG46Pol1haRBKheMO5P6nhsOEOA7VinyNyEEYVbfkEA+161lwwTFiAp24i8saUd0uMzCSlJAiK9IIHSCrnrM6Csuz9X2CD+5Cty2D7Nhqu5oh/Dh6gokhCI5fNL38lI2M6UAa7RsVc/MPPRE9dS/mTWfP+CZ7aMPf4OfkdUFXCmtC+XNDEUYCPPSU2tvxfldKOYWPuPVjxnyrL/wAHWj9wQZUuTBWVqGFgow3MD4wITAJBgUrDgMCGgUABBS+SH4ktrTO+KNlsITNvV27Zg6WiwQUmUn3r+sf9RGJS/20N9GtxTcVSPMCAwGGoA=="; // PKCS12文件路径
        String p12Password = "111111"; // PKCS12密码

        checkCertificateType(cerBase64);
        // 加载公钥
        PublicKey publicKey = loadPublicKeyFromCer(cerBase64);
        System.out.println("公钥算法: " + publicKey.getAlgorithm());

        // 加载私钥
        PrivateKey privateKey = loadPrivateKeyFromP12(p12Base64, p12Password);
        System.out.println("私钥算法: " + privateKey.getAlgorithm());

        // 2. 准备测试数据
        String originalText = "这是一段需要加密的敏感数据";
        System.out.println("原始数据: " + originalText);
        byte[] plainText = originalText.getBytes(StandardCharsets.UTF_8);

        // 3. 使用公钥加密
        byte[] encryptedData = encrypt(publicKey, plainText);
        System.out.println("加密结果(Base64): " + Base64.toBase64String(encryptedData));

        // 4. 使用私钥解密
        byte[] decryptedData = decrypt(privateKey, encryptedData);
        System.out.println("解密结果: " + new String(decryptedData, StandardCharsets.UTF_8));
    }

    public static void checkCertificateType(String cerBase64) throws Exception {
        byte[] certBytes = Base64.decode(cerBase64);
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(
                new ByteArrayInputStream(certBytes));

        System.out.println("===== 证书分析报告 =====");
        System.out.println("公钥算法: " + cert.getPublicKey().getAlgorithm());
        System.out.println("签名算法: " + cert.getSigAlgName());
        System.out.println("OID: " + cert.getSigAlgOID());
        System.out.println("是否SM2证书: " + isSM2Certificate(cert));
    }

    private static boolean isSM2Certificate(X509Certificate cert) {
        // SM2证书的OID标识
        return "1.2.156.10197.1.301".equals(cert.getSigAlgOID()) ||
                cert.getSigAlgName().toLowerCase().contains("sm2");
    }


    /**
     * 从CER证书加载公钥
     */
    public static PublicKey loadPublicKeyFromCer(String cerBase64) throws Exception {
        byte[] certBytes = Base64.decode(cerBase64);
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
        X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(
                new ByteArrayInputStream(certBytes));

        // 验证是否为EC公钥
        if (!"EC".equals(certificate.getPublicKey().getAlgorithm())) {
            throw new IllegalArgumentException("证书不是EC/SM2类型");
        }

        return certificate.getPublicKey();
    }

    /**
     * 从PKCS12文件加载私钥
     */
    public static PrivateKey loadPrivateKeyFromP12(String p12Base64, String password) throws Exception {
        KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
        ks.load(new ByteArrayInputStream(Base64.decode(p12Base64)), password.toCharArray());

        Enumeration<String> aliases = ks.aliases();
        String alias = aliases.nextElement();
        return (PrivateKey) ks.getKey(alias, password.toCharArray());
    }

    /**
     * SM2公钥加密
     */
    public static byte[] encrypt(PublicKey publicKey, byte[] plainText) throws Exception {
        if (!(publicKey instanceof BCECPublicKey)) {
            throw new IllegalArgumentException("必须是BCECPublicKey实例");
        }

        BCECPublicKey ecPublicKey = (BCECPublicKey) publicKey;
        ECParameterSpec ecParameterSpec = ecPublicKey.getParameters();

        ECDomainParameters domainParams = new ECDomainParameters(
                ecParameterSpec.getCurve(),
                ecParameterSpec.getG(),
                ecParameterSpec.getN(),
                ecParameterSpec.getH());

        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(
                ecPublicKey.getQ(),
                domainParams);

        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));

        return engine.processBlock(plainText, 0, plainText.length);
    }

    /**
     * SM2私钥解密
     */
    public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws Exception {
        if (!(privateKey instanceof BCECPrivateKey)) {
            throw new IllegalArgumentException("必须是BCECPrivateKey实例");
        }

        BCECPrivateKey ecPrivateKey = (BCECPrivateKey) privateKey;
        ECParameterSpec ecParameterSpec = ecPrivateKey.getParameters();

        ECDomainParameters domainParams = new ECDomainParameters(
                ecParameterSpec.getCurve(),
                ecParameterSpec.getG(),
                ecParameterSpec.getN(),
                ecParameterSpec.getH());

        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(
                ecPrivateKey.getD(),
                domainParams);

        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        engine.init(false, privateKeyParameters);

        return engine.processBlock(encryptedData, 0, encryptedData.length);
    }
}
